/**
 * @author Administrator
 */

(function($) {

	function calendar() {
		this.defaults = {
			monthNames : [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12],
			weekNames : ['日', '一', '二', '三', '四', '五', '六'],
			firstDay : 1,
			currentDate : new Date(),
			monthNamesShort : ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'],
			dayNames : ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'],
			dayNamesShort : ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'],
			dayNamesMin : ['Su', 'Mo', 'Tu', 'We', 'Th', 'Fr', 'Sa'],
			dateFormat : 'yy年MM月',
			init : false
		};
	}


	$.extend(calendar.prototype, {
		init : function(options,it) {
				var config = $.extend(this.defaults, options);
				$.calendar.setting = config;
				if (!config.init) {
					//append Calendar html
					var template = '<div class="danan-calendar-container" style="display:none;"><table class="danan-calendar" > <thead class="danan-calendar-body"> <tr class="monsths"> <th class="danan-calendar-title"><a href="javascript:void(0)" class="pre"><span class="danan-calendar-preMonth"></span></a><a href="javascript:void(0)" class="next"><span class="danan-calendar-nextMonth"></span></a><span class="date"></span></th> </tr> </thead> <tbody> <tr> <td><table class="danan-calendar-conont"><thead></thead><tbody></tbody> </table></td></tr></tbody></table></div>';
					$("body").append(template);
					//bind event
					$("th.danan-calendar-title a.pre,th.danan-calendar-title a.next").bind("click", function() {
						var $this = $(this);
						if ($this.hasClass('pre')) {
							$.calendar.AdustMonth(-1);
						}
						if ($this.hasClass('next')) {
							$.calendar.AdustMonth(1);
						}
					});
				var tb = $("table.danan-calendar-conont");
					//append week name
				var th = $("thead", tb);
				var template = "<tr>"
				for (var i = 0; i < config.weekNames.length; i++) {
					template += "<th>" + config.weekNames[(config.firstDay+i)%7] + "</th>";
				}
				template += "</tr" > th.append(template);
					$.calendar.updateDateView(config.currentDate);
					$.calendar.setting.init = true;
					//注册input的click事件
					if(it){
						it.each(function(){
							$(this).bind({'click':$.calendar.show});
						});
						
					}
					//注册点击别的地方，隐藏Calendar
					$(document).find('body').mousedown($.calendar.checkExternalClick);
					
				}
			

		},

		updateDateView : function(date) {
			var config = $.calendar.setting;
			config.currentDate = date;
			//get calendar days
			var y = config.currentDate.getFullYear();
			var m = config.currentDate.getMonth();
			config.days = $.calendar.getCalendarDays(y, m, config.firstDay);
			//init header
			var tb = $("table.danan-calendar-conont");
			//init body
			template = "<tr>";
			var title='';
			var isToday=false;
			var today=new Date();
			for (var i = 0; i < config.days.length; i++) {
				if (i != 0 && i % 7 == 0) {
					template += "</tr><tr>";
				}
				var day=config.days[i];
				title=this.formatDate('yy-MM-dd',new Date(day.y,day.m,day.day));
				isToday=(day.y==today.getFullYear()&&day.m==today.getMonth()&&day.day==today.getDate());
				template += "<td" + " class='" + day.disabled +(isToday?" today":"") +"'><a href='javascript:void(0)' title='"+title+"'>" + day.day + "</a></td>";
			}
			template += "</tr>"
			$("tbody", tb).empty().append(template);
			//init current days
			$("th.danan-calendar-title span.date").text($.calendar.formatDate(config.dateFormat, config.currentDate));
			$("td.false  a", tb).bind('click',$.calendar.selectDate);
		},
		selectDate:function(){
			var $this=$(this);
			$.calendar.el.val($this.attr("title"));
			$.calendar.hide();
		},
		formatDate : function(format, date, settings) {
			if (!date)
				return '';
			var dayNamesShort = ( settings ? settings.dayNamesShort : null) || this.defaults.dayNamesShort;
			var dayNames = ( settings ? settings.dayNames : null) || this.defaults.dayNames;
			var monthNamesShort = ( settings ? settings.monthNamesShort : null) || this.defaults.monthNamesShort;
			var monthNames = ( settings ? settings.monthNames : null) || this.defaults.monthNames;
			// Check whether a format character is doubled
			var lookAhead = function(match) {
				var matches = (iFormat + 1 < format.length && format.charAt(iFormat + 1) == match);
				if (matches)
					iFormat++;
				return matches;
			};
			// Format a number, with leading zero if necessary
			var formatNumber = function(match, value, len) {
				var num = '' + value;
				if (lookAhead(match))
					while (num.length < len)
					num = '0' + num;
				return num;
			};
			// Format a name, short or long as requested
			var formatName = function(match, value, shortNames, longNames) {
				return (lookAhead(match) ? longNames[value] : shortNames[value]);
			};
			var output = '';
			var literal = false;
			if (date)
				for (var iFormat = 0; iFormat < format.length; iFormat++) {
					if (literal)
						if (format.charAt(iFormat) == "'" && !lookAhead("'"))
							literal = false;
						else
							output += format.charAt(iFormat);
					else
						switch (format.charAt(iFormat)) {
							case 'd':
								output += formatNumber('d', date.getDate(), 2);
								break;
							case 'D':
								output += formatName('D', date.getDay(), dayNamesShort, dayNames);
								break;
							case 'o':
								output += formatNumber('o', Math.round((new Date(date.getFullYear(), date.getMonth(), date.getDate()).getTime() - new Date(date.getFullYear(), 0, 0).getTime()) / 86400000), 3);
								break;
							case 'm':
								output += formatNumber('m', date.getMonth() + 1, 2);
								break;
							case 'M':
								output += formatName('M', date.getMonth(), monthNamesShort, monthNames);
								break;
							case 'y':
								output += (lookAhead('y') ? date.getFullYear() : (date.getYear() % 100 < 10 ? '0' : '') + date.getYear() % 100);
								break;
							case '@':
								output += date.getTime();
								break;
							case '!':
								output += date.getTime() * 10000 + this._ticksTo1970;
								break;
							case "'":
								if (lookAhead("'"))
									output += "'";
								else
									literal = true;
								break;
							default:
								output += format.charAt(iFormat);
						}
				}
			return output;
		},

		AdustMonth : function(driction) {
			var date = $.calendar.setting.currentDate;
			var y = date.getFullYear();
			var m = date.getMonth();
			var ad = $.calendar.adjustDate(y, m, driction);
			date = new Date(ad.y, ad.m, 1);
			$.calendar.updateDateView(date);
		},


		getCalendarDays : function(y, m, dayOfWeek) {
			var startAndEnd = {
				start : new Date(y, m, 1),
				end : new Date(y, m, getMonthDays(y, m))
			};
			var startDays =changeDayTo(dayOfWeek, startAndEnd.start.getDay(), -1);
			var endDays = changeDayTo((7 - dayOfWeek + 1) % 7, startAndEnd.end.getDay(), 1);

			/*******forwar days*********/

			var preDays = getDays(startDays, y, m, -1);
			var thisMonthNum = getMonthDays(y, m);
			for (var i = 0; i < thisMonthNum; ) {
				preDays.push({
					day : ++i,
					disabled : false,
					y:y,
					m:m
				});
			}
			if (preDays.length + endDays != 42) {
				endDays += 7;
			}
			return preDays.concat(getDays(endDays, y, m, 1));

			function changeDayTo(dayOfWeek, day, direction) {
				return (Math.abs(day - dayOfWeek - (direction * 7)) % 7);
			}

			function getDays(days, y, m, driction) {
				var s = [];
				if (days != 0) {
					var ad = $.calendar.adjustDate(y, m, driction);
					var num = 0;
					if (driction == -1) {
						num = getMonthDays(ad.y, ad.m);
					}
					for (var i = 0; i < days; i++) {
						if (driction == -1) {
							s.push({
								day : num - days + i + 1,
								disabled : true,
								y:ad.y,
								m:ad.m
							});
						} else {
							s.push({
								day : i + 1,
								disabled : true,
								y:ad.y,
								m:ad.m
							});
						}
					}
				}
				return s;
			}

			function getMonthDays(y, m) {
				var monthDays = [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31];
				if (m == 2 && isLeapYear(y)) {
					return 29;
				} else {
					return monthDays[m];
				}
				function isLeapYear(year) {
					return year % 400 == 0 || (year % 4 == 0 && year % 100 != 0);
				}

			}

		},

		adjustDate : function(y, m, driction) {
			if (m == 0 && driction == -1) {
				y--;
				m = 11;
			} else if (m == 11 && driction == 1) {
				y++;
				m = 0;
			} else if(driction!=0){
				driction > 0 ? m++ : m--;
			}
			return {
				y : y,
				m : m
			};
		},
		show:function(event){
			var $this=$(this);		
			var position=$this.position();
			$.calendar.setting.curIns=true;
			$("div.danan-calendar-container").show().offset({left:position.left,top:position.top+this.offsetHeight});
		},
		hide:function(){
			$.calendar.setting.curIns=false;
			$("div.danan-calendar-container").hide();
		},
		checkExternalClick:function(event){
			if($.calendar.setting.curIns){				
			var $target=$(event.target);
			if($target.closest("div.danan-calendar-container").length<1){$.calendar.hide();}
			}
		}
	});

	$.fn.calendar = function(args) {
		if (!this.length) {
			return this;
		}
		$.calendar.el=this;
		if ($.calendar.init) {
			$.calendar.init(args,this);
		}
		// Method calling logic
		if ( typeof args === 'string') {
			return $.calendar[(args)].apply($.calendar, args);
		} else if ( typeof args === 'object' || !args) {
			return $.calendar.init(args);
		} else {
			$.error('Method ' + method + ' does not exist on jQuery.Calendar');
		}
	}

	$.calendar = new calendar();

})(jQuery);
